
#include "operacionesSectores.h"
#include "estructuras.h"
#include "operacionesFUSE.h"
#include "imprimir.h"
#include <stdio.h>
#include <stdint.h>//uintN_t N bits, http://linux.die.net/man/3/uint32_t
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>//manejar errores
#include <unistd.h>
#include <fcntl.h>//posix manejar archivos
#include <dirent.h>//posix manejar directorios
#include <sys/stat.h>

//****************************************************************************************************

int32_t abrirArchivo(const char* path){

        int32_t descriptor;
        descriptor = open(path,O_RDWR);
        if (descriptor == -1){
                perror("\nerror al abrir el archivo, no se llego a leer el sector");
                exit(-2);
        } else {return descriptor;}
}

void rellenarSector (char *ptrCadena,Sector *sector){

	for(uint32_t nroB = 0; nroB < SIZE_SECTOR; nroB++){
		(*sector).bytes[nroB]= ptrCadena[nroB];
	}

}

uint32_t calcularSector(uint32_t nroBloque){
	return (nroBloque * SIZE_BLOCK);
}

uint32_t convertirBloqueACluster(uint32_t nroBloque){

		uint32_t nroCluster;


		if ((nroBloque * SIZE_BLOCK) < DIR_DATA_REGION) {perror("no es un cluster valido"); return 0;}
		else {
			nroCluster = (((nroBloque * SIZE_BLOCK)/DIR_DATA_REGION)/SIZE_CLUSTER)+2;//????????????????????????????????????????
			return nroCluster;
		}
}



uint32_t convertirClusterAbloque(uint32_t nroCluster){

		uint32_t nroBloque;

		nroBloque = (DIR_DATA_REGION + ((nroCluster-2) * SIZE_CLUSTER)) /SIZE_BLOCK;
		return nroBloque;
}

void inicializarCache(CacheFat *cache){

		uint32_t sectorN;

		for (sectorN = 0; sectorN < SIZE_BLOCK; sectorN++){
			(*cache).sectores[sectorN].sectorReal = -2;
		}
}

void actualizarBitMap(uint32_t nroBloque){

		uint32_t nroCluster = convertirBloqueACluster(nroBloque);

		for( uint32_t nroSector = 0; nroSector < SIZE_BLOCK; nroSector++){

			uint16_t nroByte;
			for (nroByte = 0; nroByte < SIZE_SECTOR; nroByte = nroByte + 4){

				if( cacheFat.sectores[nroSector].bytes[nroByte] == 0
						&& cacheFat.sectores[nroSector].bytes[nroByte+1] == 0
						&& cacheFat.sectores[nroSector].bytes[nroByte+2] == 0
						&& cacheFat.sectores[nroSector].bytes[nroByte+3] == 0){
					vectorBitMap.bitmap[nroCluster] = 0;}
				else { vectorBitMap.bitmap[nroCluster] = 1;}
				nroCluster++;
			}
		}
}

uint32_t obtenerPrimerClusterEnFat(UbicacionCache entradaCache){

		uint8_t entrada[32];
		memcpy(entrada,&capaDir.sectores[entradaCache.nroSectorEntradaSgte].bytes[entradaCache.nroByteEntradaSgte],32);
		uint32_t nroCluster;
		uint8_t bytes[4];
		memset(bytes,0,4);
		uint8_t offset = 0x14;//high 2 bytes of first cluster number in FAT32
		bytes[2]= entrada[offset];
		bytes[3]= entrada[offset+1];
		offset = 0x1A; //low 2 bytes of first cluster number in FAT32
		bytes[0]= entrada[offset];
		bytes[1]= entrada[offset+1];
		memcpy(&nroCluster,&bytes,4);

		return nroCluster;
}

EntradaFat calcularUbicacionDeEntradaFatDel(uint32_t cluster){

	uint16_t byteComienzoEntrada;
	uint32_t cantCluster = 0;
	uint16_t nroSector;
	uint32_t bloque = 0;
	uint32_t sectorX = 0;
	EntradaFat ubicacion;

	for (nroSector = 0; nroSector < SECTORS_PER_FAT; nroSector++){

		for( byteComienzoEntrada = 0; byteComienzoEntrada < SIZE_SECTOR; byteComienzoEntrada = byteComienzoEntrada+4 ){

			if (cluster == cantCluster){
				ubicacion.bloque = (nroSector/SIZE_BLOCK) + (DIR_FAT1/SIZE_BLOCK);
				ubicacion.sector = sectorX;
				ubicacion.byteComienzoEntrada = byteComienzoEntrada;//valor literal cluster 2 = entrada 2; parte de 0!
				return ubicacion;
			}
			cantCluster++;
		}
		if( (nroSector % 8) == 0){bloque++; sectorX = 0;}
		sectorX++;
	}
	ubicacion.sector = ERROR_BYTES_NOT;
	return ubicacion;
}

uint32_t convertirClusterAPosicionFat_Bloque(uint32_t nroCluster){

	uint32_t posicionFat;

	posicionFat = 32+((nroCluster*4)/SIZE_SECTOR);
	return (posicionFat/8);//devuelve el bloque real de la FAT donde se encuentra el cluster


/*	uint32_t posicionFat;

	posicionFat = (nroCluster/CANT_ENTRADAS_FAT_POR_SECTOR);
	return ((posicionFat + DIR_FAT1) /8);//devuelve el bloque real de la FAT donde se encuentra el cluster
*/
}

uint32_t obtenerClusterSiguienteEnLaFat(EntradaFat entrada){

	uint8_t bufferCache[4];
		memcpy(bufferCache, &cacheFat.sectores[entrada.sector].bytes[entrada.byteComienzoEntrada],SIZE_ENTRADA_FAT);
		uint32_t nroClusSgte;//obtiene nroCluster sgte de la fat
		memcpy(&nroClusSgte,bufferCache,4);
		return nroClusSgte;
}

void guardarDatosApartirDe(int32_t *bytesLeidos,off_t offsetFile, char* dataBuffer,uint32_t fileSize, aux ubicacionOffset,size_t dataBufferSize){

	uint16_t nroSector;
	int32_t caracter = 0;
	uint32_t byte;
	uint32_t byteAux;

	byteAux = ubicacionOffset.byte;
	caracter = *bytesLeidos;

	for( nroSector = ubicacionOffset.sector; nroSector < SIZE_BLOCK; nroSector++){

		for( byte = byteAux; byte < SIZE_SECTOR; byte++){

			dataBuffer[caracter] = capaDir.sectores[nroSector].bytes[byte];
			caracter++;

			if(( ((*bytesLeidos)) == dataBufferSize)||(((*bytesLeidos)+offsetFile) == fileSize)){
				return;
			}
			(*bytesLeidos)++;
		}
		byteAux = 0;
	}
}



